`timescale 1ns / 1ps
// (C) 2021 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module ngsx #(parameter IN_BYTE_REGS = 1,                                     //to define the amount of byte registers that are received by this slave
              parameter OUT_BYTE_REGS = 1,
			  parameter   RST_VALUE_IN = 0,
			  parameter  RST_VALUE_OUT = 0)                                    //to define the amount of byte registers that are transmitted by this slave
(
 // active low reset signal (driven from internal FPGA logic)
    input               iRst_n,
 // serial clock (driven from SGPIO master)
    input               iClk,
 // Load signal (driven from SGPIO master to capture serial data input in parallel register)
    input               iLoad,
 // Serial data input (driven from SGPIO master)
    input               iSData,
 // Parallel data from internal logic to master
    input [(OUT_BYTE_REGS*8)-1:0] iPData,
 // Serial data output to SGPIO master
    output                       oSData,
 // Parallel data to internal registers (slave)
    output reg [(IN_BYTE_REGS*8)-1:0] oPData
);
      

// Internal Signals

   reg [(IN_BYTE_REGS*8)-1:0] rSToPAcc;   //Serial to Parallel Accumulator (for serial data from SGPIO master). Goes to internal registers
   reg [(OUT_BYTE_REGS*8)-1:0] rPDataIn;   //parallel data input register (to latch data before serializing), goes to SGPIO master
   
//////////////////////////////////////////////////////////////////////////////////
// Continous assigments
//////////////////////////////////////////////////////////////////////////////////
   
   assign oSData = rPDataIn[(OUT_BYTE_REGS*8) - 1];        //serial output is the MSb of the shifted register

//////////////////////////////////////////////////////////////////////////////////
// Sequential logic
//////////////////////////////////////////////////////////////////////////////////

always @(posedge iClk, negedge iRst_n)
  begin
     if (!iRst_n)   //synchronous reset condition for outputs and internal signals
       begin
          rSToPAcc <= RST_VALUE_IN;
          oPData <= RST_VALUE_IN;
          rPDataIn <= RST_VALUE_OUT;
       end //if (!rst_n)
     else //not(if (!rst_n))
       begin
          //logic for serial data coming from SGPIO Master that goes to internal logic
          rSToPAcc = {rSToPAcc[(IN_BYTE_REGS*8)-2:0], iSData};
          
          if (!iLoad)  //parallel data is captured to start serialization for data that goes to SGPIO Master
            begin
               rPDataIn <= iPData;
               oPData <= rSToPAcc;
            end //if (!iLoad)
          else 
            begin
               rPDataIn[OUT_BYTE_REGS*8 - 1:0] <= {rPDataIn[OUT_BYTE_REGS*8 - 2:0], 1'b0};   //shifting register to serialize parallel input
            end //not(if (!iLoad))
          
       end // else: !if(!iRst_n)
  end // always @ (posedge iClk, negedge iRst_n)
   
endmodule //module NGSX
